import mongoose, { Document, Schema, Model } from 'mongoose';

/**
 * 权限接口定义
 * 定义权限的基本属性
 */
export interface IPermission {
  /** 权限名称 */
  name: string;
  /** 权限编码，唯一标识 */
  code: string;
  /** 权限类型：page/route/component/button/api/data */
  type: string;
  /** 所属系统ID */
  systemId?: mongoose.Types.ObjectId;
  /** 父权限ID */
  parentId?: mongoose.Types.ObjectId;
  /** 权限路径 */
  path?: string;
  /** HTTP方法（API权限） */
  method?: string;
  /** API接口路径 */
  apiPath?: string;
  /** 数据权限范围：all/dept/self/custom */
  dataScope?: string;
  /** 权限描述 */
  description?: string;
  /** 排序 */
  sort: number;
  /** 状态：1-正常，0-禁用 */
  status: number;
  /** 是否系统权限 */
  isSystem: boolean;
  /** 依赖权限ID列表 */
  dependencies: mongoose.Types.ObjectId[];
  /** 创建时间 */
  createdAt: Date;
  /** 更新时间 */
  updatedAt: Date;
}

/**
 * 权限文档接口
 * 继承IPermission接口和mongoose的Document接口
 */
export interface IPermissionDocument extends IPermission, Document {
  /**
   * 转换为JSON格式，用于API响应
   * @returns 格式化的权限对象
   */
  toJSON(): any;

  /**
   * 检查权限是否为系统权限
   * @returns 是否为系统权限
   */
  isSystemPermission(): boolean;

  /**
   * 检查权限是否可以被删除
   * @returns 是否可以删除
   */
  canBeDeleted(): Promise<boolean>;

  /**
   * 获取权限的子权限数量
   * @returns 子权限数量
   */
  getChildrenCount(): Promise<number>;

  /**
   * 获取使用该权限的角色数量
   * @returns 角色数量
   */
  getRoleCount(): Promise<number>;

  /**
   * 获取权限的依赖权限列表
   * @returns 依赖权限列表
   */
  getDependencies(): Promise<IPermissionDocument[]>;

  /**
   * 检查权限依赖关系是否存在循环
   * @returns 是否存在循环依赖
   */
  hasCircularDependency(): Promise<boolean>;
}

/**
 * 权限模型接口
 * 定义权限模型的静态方法
 */
export interface IPermissionModel extends Model<IPermissionDocument> {
  /**
   * 根据权限编码查找权限
   * @param code 权限编码
   * @returns 权限文档或null
   */
  findByCode(code: string): Promise<IPermissionDocument | null>;

  /**
   * 根据权限名称查找权限
   * @param name 权限名称
   * @returns 权限文档或null
   */
  findByName(name: string): Promise<IPermissionDocument | null>;

  /**
   * 根据系统ID查找权限
   * @param systemId 系统ID
   * @returns 权限文档数组
   */
  findBySystemId(systemId: mongoose.Types.ObjectId): Promise<IPermissionDocument[]>;

  /**
   * 根据权限类型查找权限
   * @param type 权限类型
   * @returns 权限文档数组
   */
  findByType(type: string): Promise<IPermissionDocument[]>;

  /**
   * 根据父权限ID查找子权限
   * @param parentId 父权限ID
   * @returns 权限文档数组
   */
  findByParentId(parentId: mongoose.Types.ObjectId): Promise<IPermissionDocument[]>;

  /**
   * 根据状态查找权限
   * @param status 状态
   * @returns 权限文档数组
   */
  findByStatus(status: number): Promise<IPermissionDocument[]>;

  /**
   * 获取系统内置权限
   * @returns 系统权限文档数组
   */
  getSystemPermissions(): Promise<IPermissionDocument[]>;

  /**
   * 构建权限树结构
   * @param systemId 系统ID（可选）
   * @returns 权限树结构
   */
  buildPermissionTree(systemId?: mongoose.Types.ObjectId): Promise<any[]>;

  /**
   * 检查权限编码是否存在
   * @param code 权限编码
   * @param excludeId 排除的权限ID
   * @returns 是否存在
   */
  isCodeExists(code: string, excludeId?: mongoose.Types.ObjectId): Promise<boolean>;

  /**
   * 检查权限名称是否存在
   * @param name 权限名称
   * @param excludeId 排除的权限ID
   * @returns 是否存在
   */
  isNameExists(name: string, excludeId?: mongoose.Types.ObjectId): Promise<boolean>;

  /**
   * 根据API路径和方法查找权限
   * @param apiPath API路径
   * @param method HTTP方法
   * @returns 权限文档或null
   */
  findByApiPath(apiPath: string, method: string): Promise<IPermissionDocument | null>;

  /**
   * 批量创建权限
   * @param permissions 权限数据数组
   * @returns 创建的权限文档数组
   */
  batchCreate(permissions: Partial<IPermission>[]): Promise<IPermissionDocument[]>;
}

/**
 * 权限Schema定义
 */
const PermissionSchema = new Schema<IPermissionDocument>({
  // 权限名称
  name: {
    type: String,
    required: [true, '权限名称不能为空'],
    trim: true,
    maxlength: [100, '权限名称不能超过100个字符'],
    index: true
  },

  // 权限编码
  code: {
    type: String,
    required: [true, '权限编码不能为空'],
    unique: true,
    trim: true,
    maxlength: [50, '权限编码不能超过50个字符'],
    match: [/^[a-zA-Z0-9_:.-]+$/, '权限编码只能包含字母、数字、下划线、冒号、点和横线'],
    index: true
  },

  // 权限类型
  type: {
    type: String,
    required: [true, '权限类型不能为空'],
    enum: {
      values: ['page', 'route', 'component', 'button', 'api', 'data'],
      message: '权限类型必须是：page、route、component、button、api、data之一'
    },
    index: true
  },

  // 所属系统ID
  systemId: {
    type: Schema.Types.ObjectId,
    ref: 'System',
    index: true
  },

  // 父权限ID
  parentId: {
    type: Schema.Types.ObjectId,
    ref: 'Permission',
    index: true
  },

  // 权限路径
  path: {
    type: String,
    trim: true,
    maxlength: [200, '权限路径不能超过200个字符']
  },

  // HTTP方法
  method: {
    type: String,
    trim: true,
    uppercase: true,
    enum: {
      values: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'],
      message: 'HTTP方法必须是有效的HTTP动词'
    }
  },

  // API接口路径
  apiPath: {
    type: String,
    trim: true,
    maxlength: [200, 'API路径不能超过200个字符']
  },

  // 数据权限范围
  dataScope: {
    type: String,
    enum: {
      values: ['all', 'dept', 'self', 'custom'],
      message: '数据权限范围必须是：all、dept、self、custom之一'
    },
    default: 'all'
  },

  // 权限描述
  description: {
    type: String,
    trim: true,
    maxlength: [500, '权限描述不能超过500个字符']
  },

  // 排序
  sort: {
    type: Number,
    default: 0,
    min: [0, '排序值不能小于0'],
    index: true
  },

  // 状态
  status: {
    type: Number,
    required: true,
    enum: [0, 1],
    default: 1,
    index: true
  },

  // 是否系统权限
  isSystem: {
    type: Boolean,
    default: false,
    index: true
  },

  // 依赖权限ID列表
  dependencies: {
    type: [Schema.Types.ObjectId],
    ref: 'Permission',
    default: []
  }
}, {
  // 自动添加创建时间和更新时间
  timestamps: true,
  // 集合名称
  collection: 'permissions',
  // 禁用版本键
  versionKey: false
});

// 创建复合索引
PermissionSchema.index({ code: 1 }, { unique: true });
PermissionSchema.index({ systemId: 1, type: 1 });
PermissionSchema.index({ systemId: 1, status: 1 });
PermissionSchema.index({ parentId: 1, sort: 1 });
PermissionSchema.index({ type: 1, status: 1 });
PermissionSchema.index({ apiPath: 1, method: 1 });
PermissionSchema.index({ status: 1, createdAt: -1 });
PermissionSchema.index({ isSystem: 1, status: 1 });

// 保存前中间件：处理编码转换和默认值设置
PermissionSchema.pre('save', function(next) {
  // 如果是新文档或者code字段被修改，转换为小写
  if (this.isNew || this.isModified('code')) {
    this.code = this.code.toLowerCase();
  }
  
  // 如果是新文档，设置默认值
  if (this.isNew) {
    // 只有当status未定义时才设置默认值，避免覆盖显式设置的0值
    if (this.status === undefined) {
      this.status = 1;
    }
  }
  
  next();
});

// 更新前中间件：处理更新操作
PermissionSchema.pre(['updateOne', 'findOneAndUpdate'], function(next) {
  const update = this.getUpdate() as any;
  
  // 如果更新了code字段，转换为小写
  if (update.code) {
    update.code = update.code.toLowerCase();
  }
  
  // 自动更新updatedAt字段
  update.updatedAt = new Date();
  
  next();
});

// 实例方法：转换为JSON格式
PermissionSchema.methods.toJSON = function() {
  const obj = this.toObject();
  
  // 移除敏感字段
  delete obj.__v;
  
  // 格式化时间字段
  if (obj.createdAt) {
    obj.createdAt = obj.createdAt.toISOString();
  }
  if (obj.updatedAt) {
    obj.updatedAt = obj.updatedAt.toISOString();
  }
  
  return obj;
};

// 实例方法：检查是否为系统权限
PermissionSchema.methods.isSystemPermission = function(): boolean {
  return this.isSystem === true;
};

// 实例方法：检查是否可以被删除
PermissionSchema.methods.canBeDeleted = async function(): Promise<boolean> {
  // 系统权限不能删除
  if (this.isSystem) {
    return false;
  }
  
  // 临时返回true，后续需要检查是否有角色使用该权限
  return true;
};

// 实例方法：获取子权限数量
PermissionSchema.methods.getChildrenCount = async function(): Promise<number> {
  // 临时返回0，后续实现
  return 0;
};

// 实例方法：获取使用该权限的角色数量
PermissionSchema.methods.getRoleCount = async function(): Promise<number> {
  // 临时返回0，后续实现
  return 0;
};

// 实例方法：获取权限的依赖权限列表
PermissionSchema.methods.getDependencies = async function(): Promise<IPermissionDocument[]> {
  if (!this.dependencies || this.dependencies.length === 0) {
    return [];
  }
  
  return await Permission.find({
    _id: { $in: this.dependencies },
    status: 1
  }).sort({ sort: 1, createdAt: -1 });
};

// 实例方法：检查权限依赖关系是否存在循环
PermissionSchema.methods.hasCircularDependency = async function(): Promise<boolean> {
  // 临时返回false，后续实现循环依赖检测算法
  return false;
};

// 静态方法：根据编码查找权限
PermissionSchema.statics.findByCode = function(code: string): Promise<IPermissionDocument | null> {
  return this.findOne({ code: code.toLowerCase() });
};

// 静态方法：根据名称查找权限
PermissionSchema.statics.findByName = function(name: string): Promise<IPermissionDocument | null> {
  return this.findOne({ name });
};

// 静态方法：根据系统ID查找权限
PermissionSchema.statics.findBySystemId = function(systemId: mongoose.Types.ObjectId): Promise<IPermissionDocument[]> {
  return this.find({ systemId }).sort({ sort: 1, createdAt: -1 });
};

// 静态方法：根据权限类型查找权限
PermissionSchema.statics.findByType = function(type: string): Promise<IPermissionDocument[]> {
  return this.find({ type }).sort({ sort: 1, createdAt: -1 });
};

// 静态方法：根据父权限ID查找子权限
PermissionSchema.statics.findByParentId = function(parentId: mongoose.Types.ObjectId): Promise<IPermissionDocument[]> {
  return this.find({ parentId }).sort({ sort: 1, createdAt: -1 });
};

// 静态方法：根据状态查找权限
PermissionSchema.statics.findByStatus = function(status: number): Promise<IPermissionDocument[]> {
  return this.find({ status }).sort({ sort: 1, createdAt: -1 });
};

// 静态方法：获取系统内置权限
PermissionSchema.statics.getSystemPermissions = function(): Promise<IPermissionDocument[]> {
  return this.find({ 
    isSystem: true,
    status: 1 
  }).sort({ sort: 1, createdAt: -1 });
};

// 静态方法：构建权限树结构
PermissionSchema.statics.buildPermissionTree = async function(systemId?: mongoose.Types.ObjectId): Promise<any[]> {
  const query: any = { status: 1 };
  if (systemId) {
    query.systemId = systemId;
  }
  
  const permissions = await this.find(query).sort({ sort: 1, createdAt: -1 });
  
  // 构建树结构的递归函数
  const buildTree = (parentId: mongoose.Types.ObjectId | null = null): any[] => {
    return permissions
      .filter((permission: IPermissionDocument) => {
        if (parentId === null) {
          return !permission.parentId;
        }
        return permission.parentId && permission.parentId.toString() === parentId.toString();
      })
      .map((permission: IPermissionDocument) => ({
        ...permission.toJSON(),
        children: buildTree(permission._id as mongoose.Types.ObjectId)
      }));
  };
  
  return buildTree();
};

// 静态方法：检查权限编码是否存在
PermissionSchema.statics.isCodeExists = async function(
  code: string, 
  excludeId?: mongoose.Types.ObjectId
): Promise<boolean> {
  const query: any = { code: code.toLowerCase() };
  if (excludeId) {
    query._id = { $ne: excludeId };
  }
  
  const permission = await this.findOne(query);
  return !!permission;
};

// 静态方法：检查权限名称是否存在
PermissionSchema.statics.isNameExists = async function(
  name: string, 
  excludeId?: mongoose.Types.ObjectId
): Promise<boolean> {
  const query: any = { name };
  if (excludeId) {
    query._id = { $ne: excludeId };
  }
  
  const permission = await this.findOne(query);
  return !!permission;
};

// 静态方法：根据API路径和方法查找权限
PermissionSchema.statics.findByApiPath = function(apiPath: string, method: string): Promise<IPermissionDocument | null> {
  return this.findOne({ 
    apiPath, 
    method: method.toUpperCase(),
    type: 'api',
    status: 1
  });
};

// 静态方法：批量创建权限
PermissionSchema.statics.batchCreate = async function(permissions: Partial<IPermission>[]): Promise<IPermissionDocument[]> {
  const result = await this.insertMany(permissions);
  return result as IPermissionDocument[];
};

// 导出权限模型
export const Permission = mongoose.model<IPermissionDocument, IPermissionModel>('Permission', PermissionSchema);

export default Permission;